Чтобы скорректировать рекламный бюджет, коммерческий департамент хочет понять, какой тариф приносит больше денег.
Вам предстоит сделать предварительный анализ тарифов на небольшой выборке клиентов. В вашем распоряжении данные 500 пользователей «Мегалайна»: кто они, откуда, каким тарифом пользуются, сколько звонков и сообщений каждый отправил за 2018 год. Нужно проанализировать поведение клиентов и сделать вывод — какой тариф лучше.
Для начала просмотрим, какие датасеты представлены на анализ, изучим тип данных, и просмотрим первые строки.
!pip install plotly.express -U
Collecting plotly.express Downloading plotly_express-0.4.1-py2.py3-none-any.whl (2.9 kB) Requirement already satisfied, skipping upgrade: patsy>=0.5 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (0.5.1) Requirement already satisfied, skipping upgrade: scipy>=0.18 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.5.2) Requirement already satisfied, skipping upgrade: numpy>=1.11 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.19.2) Requirement already satisfied, skipping upgrade: statsmodels>=0.9.0 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (0.12.0) Requirement already satisfied, skipping upgrade: pandas>=0.20.0 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.1.3) Collecting plotly>=4.1.0 Downloading plotly-5.3.1-py2.py3-none-any.whl (23.9 MB) Requirement already satisfied, skipping upgrade: six in c:\programdata\anaconda3\lib\site-packages (from patsy>=0.5->plotly.express) (1.15.0) Requirement already satisfied, skipping upgrade: pytz>=2017.2 in c:\programdata\anaconda3\lib\site-packages (from pandas>=0.20.0->plotly.express) (2020.1) Requirement already satisfied, skipping upgrade: python-dateutil>=2.7.3 in c:\programdata\anaconda3\lib\site-packages (from pandas>=0.20.0->plotly.express) (2.8.1) Collecting tenacity>=6.2.0 Downloading tenacity-8.0.1-py3-none-any.whl (24 kB) Installing collected packages: tenacity, plotly, plotly.express Successfully installed plotly-5.3.1 plotly.express tenacity-8.0.1
import pandas as pd
import plotly.express as px
from scipy import stats as st
import numpy as np
data_users=pd.read_csv('users.csv')
data_users.head(10)
| user_id | age | churn_date | city | first_name | last_name | reg_date | tariff | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1000 | 52 | NaN | Краснодар | Рафаил | Верещагин | 2018-05-25 | ultra |
| 1 | 1001 | 41 | NaN | Москва | Иван | Ежов | 2018-11-01 | smart |
| 2 | 1002 | 59 | NaN | Стерлитамак | Евгений | Абрамович | 2018-06-17 | smart |
| 3 | 1003 | 23 | NaN | Москва | Белла | Белякова | 2018-08-17 | ultra |
| 4 | 1004 | 68 | NaN | Новокузнецк | Татьяна | Авдеенко | 2018-05-14 | ultra |
| 5 | 1005 | 67 | NaN | Набережные Челны | Афанасий | Горлов | 2018-01-25 | smart |
| 6 | 1006 | 21 | NaN | Ульяновск | Леонид | Ермолаев | 2018-02-26 | smart |
| 7 | 1007 | 65 | NaN | Москва | Юна | Березина | 2018-04-19 | smart |
| 8 | 1008 | 63 | NaN | Челябинск | Рустэм | Пономарёв | 2018-12-19 | smart |
| 9 | 1009 | 24 | NaN | Пермь | Василиса | Блинова | 2018-03-22 | smart |
data_users.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 500 entries, 0 to 499 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 500 non-null int64 1 age 500 non-null int64 2 churn_date 38 non-null object 3 city 500 non-null object 4 first_name 500 non-null object 5 last_name 500 non-null object 6 reg_date 500 non-null object 7 tariff 500 non-null object dtypes: int64(2), object(6) memory usage: 31.4+ KB
data_calls=pd.read_csv('calls.csv')
data_calls.head(10)
| id | call_date | duration | user_id | |
|---|---|---|---|---|
| 0 | 1000_0 | 2018-07-25 | 0.00 | 1000 |
| 1 | 1000_1 | 2018-08-17 | 0.00 | 1000 |
| 2 | 1000_2 | 2018-06-11 | 2.85 | 1000 |
| 3 | 1000_3 | 2018-09-21 | 13.80 | 1000 |
| 4 | 1000_4 | 2018-12-15 | 5.18 | 1000 |
| 5 | 1000_5 | 2018-11-02 | 0.00 | 1000 |
| 6 | 1000_6 | 2018-10-18 | 0.00 | 1000 |
| 7 | 1000_7 | 2018-08-22 | 18.31 | 1000 |
| 8 | 1000_8 | 2018-09-15 | 18.44 | 1000 |
| 9 | 1000_9 | 2018-08-15 | 0.00 | 1000 |
data_calls.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 202607 entries, 0 to 202606 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 202607 non-null object 1 call_date 202607 non-null object 2 duration 202607 non-null float64 3 user_id 202607 non-null int64 dtypes: float64(1), int64(1), object(2) memory usage: 6.2+ MB
data_messages = pd.read_csv('messages.csv')
data_messages.head(10)
| id | message_date | user_id | |
|---|---|---|---|
| 0 | 1000_0 | 2018-06-27 | 1000 |
| 1 | 1000_1 | 2018-10-08 | 1000 |
| 2 | 1000_2 | 2018-08-04 | 1000 |
| 3 | 1000_3 | 2018-06-16 | 1000 |
| 4 | 1000_4 | 2018-12-05 | 1000 |
| 5 | 1000_5 | 2018-06-20 | 1000 |
| 6 | 1000_6 | 2018-11-19 | 1000 |
| 7 | 1000_7 | 2018-10-29 | 1000 |
| 8 | 1000_8 | 2018-06-25 | 1000 |
| 9 | 1000_9 | 2018-12-18 | 1000 |
data_messages.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 123036 entries, 0 to 123035 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 123036 non-null object 1 message_date 123036 non-null object 2 user_id 123036 non-null int64 dtypes: int64(1), object(2) memory usage: 2.8+ MB
data_tariffs = pd.read_csv('tariffs.csv')
data_tariffs.head(10)
| messages_included | mb_per_month_included | minutes_included | rub_monthly_fee | rub_per_gb | rub_per_message | rub_per_minute | tariff_name | |
|---|---|---|---|---|---|---|---|---|
| 0 | 50 | 15360 | 500 | 550 | 200 | 3 | 3 | smart |
| 1 | 1000 | 30720 | 3000 | 1950 | 150 | 1 | 1 | ultra |
data_tariffs.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 2 entries, 0 to 1 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 messages_included 2 non-null int64 1 mb_per_month_included 2 non-null int64 2 minutes_included 2 non-null int64 3 rub_monthly_fee 2 non-null int64 4 rub_per_gb 2 non-null int64 5 rub_per_message 2 non-null int64 6 rub_per_minute 2 non-null int64 7 tariff_name 2 non-null object dtypes: int64(7), object(1) memory usage: 256.0+ bytes
data_internet = pd.read_csv('internet.csv')
data_internet.head(10)
| Unnamed: 0 | id | mb_used | session_date | user_id | |
|---|---|---|---|---|---|
| 0 | 0 | 1000_0 | 112.95 | 2018-11-25 | 1000 |
| 1 | 1 | 1000_1 | 1052.81 | 2018-09-07 | 1000 |
| 2 | 2 | 1000_2 | 1197.26 | 2018-06-25 | 1000 |
| 3 | 3 | 1000_3 | 550.27 | 2018-08-22 | 1000 |
| 4 | 4 | 1000_4 | 302.56 | 2018-09-24 | 1000 |
| 5 | 5 | 1000_5 | 399.97 | 2018-10-02 | 1000 |
| 6 | 6 | 1000_6 | 540.08 | 2018-09-07 | 1000 |
| 7 | 7 | 1000_7 | 415.70 | 2018-07-11 | 1000 |
| 8 | 8 | 1000_8 | 505.40 | 2018-10-08 | 1000 |
| 9 | 9 | 1000_9 | 345.54 | 2018-09-03 | 1000 |
data_internet.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 149396 entries, 0 to 149395 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Unnamed: 0 149396 non-null int64 1 id 149396 non-null object 2 mb_used 149396 non-null float64 3 session_date 149396 non-null object 4 user_id 149396 non-null int64 dtypes: float64(1), int64(2), object(2) memory usage: 5.7+ MB
Первичное ознакомление с данными не дает точного представления о пропущенных и ошибочных данных. В этом пункте прочитали датасеты сохранили их в переменных, при помощи метода info() посмотрели инофрмацию о пропусках и типах данных.
Для начала приведем данные к нужному типу в таблице users, приведет дату регистрации к формату даты и времени.
data_users['reg_date'] = pd.to_datetime(data_users['reg_date'],format= '%Y-%m-%d')
data_users.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 500 entries, 0 to 499 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 500 non-null int64 1 age 500 non-null int64 2 churn_date 38 non-null object 3 city 500 non-null object 4 first_name 500 non-null object 5 last_name 500 non-null object 6 reg_date 500 non-null datetime64[ns] 7 tariff 500 non-null object dtypes: datetime64[ns](1), int64(2), object(5) memory usage: 31.4+ KB
print(data_users.duplicated().sum())
0
Приступим к анализу таблицы calls приведем все к одному типу данных, и поработаем со значениями.Приведем дату звонка к формату даты.
data_calls['call_date'] = pd.to_datetime(data_calls['call_date'],format= '%Y-%m-%d')
data_calls.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 202607 entries, 0 to 202606 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 202607 non-null object 1 call_date 202607 non-null datetime64[ns] 2 duration 202607 non-null float64 3 user_id 202607 non-null int64 dtypes: datetime64[ns](1), float64(1), int64(1), object(1) memory usage: 6.2+ MB
data_calls['duration'].value_counts()
0.00 39613
4.49 142
5.50 142
6.15 141
6.38 141
...
27.02 1
26.19 1
25.34 1
27.13 1
24.28 1
Name: duration, Length: 2871, dtype: int64
data_calls['duration']=np.ceil(data_calls['duration'])
display(data_calls.head(10))
| id | call_date | duration | user_id | |
|---|---|---|---|---|
| 0 | 1000_0 | 2018-07-25 | 0.0 | 1000 |
| 1 | 1000_1 | 2018-08-17 | 0.0 | 1000 |
| 2 | 1000_2 | 2018-06-11 | 3.0 | 1000 |
| 3 | 1000_3 | 2018-09-21 | 14.0 | 1000 |
| 4 | 1000_4 | 2018-12-15 | 6.0 | 1000 |
| 5 | 1000_5 | 2018-11-02 | 0.0 | 1000 |
| 6 | 1000_6 | 2018-10-18 | 0.0 | 1000 |
| 7 | 1000_7 | 2018-08-22 | 19.0 | 1000 |
| 8 | 1000_8 | 2018-09-15 | 19.0 | 1000 |
| 9 | 1000_9 | 2018-08-15 | 0.0 | 1000 |
Округлили длительность звонка в большую сторону, теперь можно привести их к целочисленному типу данных.
data_calls['duration']=data_calls['duration'].astype('int')
data_calls.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 202607 entries, 0 to 202606 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 202607 non-null object 1 call_date 202607 non-null datetime64[ns] 2 duration 202607 non-null int32 3 user_id 202607 non-null int64 dtypes: datetime64[ns](1), int32(1), int64(1), object(1) memory usage: 5.4+ MB
data_messages['message_date'] = pd.to_datetime(data_messages['message_date'],format= '%Y-%m-%d')
data_messages.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 123036 entries, 0 to 123035 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 123036 non-null object 1 message_date 123036 non-null datetime64[ns] 2 user_id 123036 non-null int64 dtypes: datetime64[ns](1), int64(1), object(1) memory usage: 2.8+ MB
data_messages.head()
| id | message_date | user_id | |
|---|---|---|---|
| 0 | 1000_0 | 2018-06-27 | 1000 |
| 1 | 1000_1 | 2018-10-08 | 1000 |
| 2 | 1000_2 | 2018-08-04 | 1000 |
| 3 | 1000_3 | 2018-06-16 | 1000 |
| 4 | 1000_4 | 2018-12-05 | 1000 |
data_internet.head()
| Unnamed: 0 | id | mb_used | session_date | user_id | |
|---|---|---|---|---|---|
| 0 | 0 | 1000_0 | 112.95 | 2018-11-25 | 1000 |
| 1 | 1 | 1000_1 | 1052.81 | 2018-09-07 | 1000 |
| 2 | 2 | 1000_2 | 1197.26 | 2018-06-25 | 1000 |
| 3 | 3 | 1000_3 | 550.27 | 2018-08-22 | 1000 |
| 4 | 4 | 1000_4 | 302.56 | 2018-09-24 | 1000 |
data_internet['mb_used'].value_counts()
0.00 19598
197.56 9
447.30 9
335.91 9
108.95 8
...
72.49 1
846.22 1
429.17 1
899.03 1
483.87 1
Name: mb_used, Length: 70003, dtype: int64
data_internet['mb_used'].unique()
array([ 112.95, 1052.81, 1197.26, ..., 460.75, 247.59, 23.72])
Добавим столбец с информацией о расходуемых гигабайтах.
data_internet['gb_used']=np.ceil(data_internet['mb_used'] / 1024)
data_internet['gb_used'].value_counts()
1.0 127454 0.0 19598 2.0 2344 Name: gb_used, dtype: int64
Сосчитали информацию о количестве смс и звонков каждого клиента по месячно. Для дальнейших расчетов произведем объединение таблиц.
data_messages['month'] = data_messages['message_date'].dt.month
messages = data_messages.groupby(['user_id','month']).agg('count')
messages = messages['id']
display(messages)
user_id month
1000 5 22
6 60
7 75
8 81
9 57
..
1498 10 42
1499 9 11
10 48
11 59
12 66
Name: id, Length: 2717, dtype: int64
data_calls['month'] = data_calls['call_date'].dt.month
calls = data_calls.groupby(['user_id','month']).agg('sum')
#calls
data_messages['month'] = data_messages['message_date'].dt.month
messages = data_messages.groupby(['user_id','month']).agg('count')
messages = messages['id']
data_internet['session_date'] = pd.to_datetime(data_internet['session_date'],format= '%Y-%m-%d')
data_internet['month'] = data_internet['session_date'].dt.month
internet= data_internet.groupby(['user_id','month']).agg('sum')
internet = internet['mb_used']
revenue = calls.join(internet,on = ['user_id','month'],how = 'outer')
revenue = revenue.join(messages,on = ['user_id','month'],how = 'outer')
tariff_name = data_users.loc[:,['user_id','tariff','city']].set_index('user_id')
revenue = revenue.join(tariff_name,how = 'outer')
revenue = revenue.reset_index()
revenue.columns = ['user_id','month','sum_duration','sum_mb','count_messages','tariff','city']
revenue
| user_id | month | sum_duration | sum_mb | count_messages | tariff | city | |
|---|---|---|---|---|---|---|---|
| 0 | 1000 | 5 | 159.0 | 2253.49 | 22.0 | ultra | Краснодар |
| 1 | 1000 | 6 | 172.0 | 23233.77 | 60.0 | ultra | Краснодар |
| 2 | 1000 | 7 | 340.0 | 14003.64 | 75.0 | ultra | Краснодар |
| 3 | 1000 | 8 | 408.0 | 14055.93 | 81.0 | ultra | Краснодар |
| 4 | 1000 | 9 | 466.0 | 14568.91 | 57.0 | ultra | Краснодар |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 3209 | 1489 | 8 | NaN | 11050.56 | 17.0 | smart | Санкт-Петербург |
| 3210 | 1489 | 9 | NaN | 17206.30 | 32.0 | smart | Санкт-Петербург |
| 3211 | 1489 | 10 | NaN | 19559.44 | 21.0 | smart | Санкт-Петербург |
| 3212 | 1489 | 11 | NaN | 17491.56 | 20.0 | smart | Санкт-Петербург |
| 3213 | 1489 | 12 | NaN | 17322.51 | 35.0 | smart | Санкт-Петербург |
3214 rows × 7 columns
В одной табличке собрана информация, о всех расходуемых пакетах, связь, сообщения, интернет, теперь можно посчитать прибыль.
list(data_tariffs.columns.values)
['messages_included', 'mb_per_month_included', 'minutes_included', 'rub_monthly_fee', 'rub_per_gb', 'rub_per_message', 'rub_per_minute', 'tariff_name']
display(data_tariffs)
| messages_included | mb_per_month_included | minutes_included | rub_monthly_fee | rub_per_gb | rub_per_message | rub_per_minute | tariff_name | |
|---|---|---|---|---|---|---|---|---|
| 0 | 50 | 15360 | 500 | 550 | 200 | 3 | 3 | smart |
| 1 | 1000 | 30720 | 3000 | 1950 | 150 | 1 | 1 | ultra |
messages_include_smart = 50
messages_include_ultra = 1000
mb_included_smart = 15360
mb_included_ultra = 30720
minutes_included_smart = 500
minutes_included_ultra = 3000
coast_smart = 550
coast_ultra = 1950
coast_gb_smart = 200
coast_gb_ultra = 150
coast_minmes_smart = 3
coast_minmes_ultra = 1
def revenue_calculation (row):
name_tariff = row['tariff']
if name_tariff == 'smart':
summ = coast_smart
if row['sum_duration'] > minutes_included_smart:
summ = summ + ((row['sum_duration'] - minutes_included_smart) * coast_minmes_smart)
if row['count_messages'] > messages_include_smart:
summ = summ + ((row['count_messages']-messages_include_smart) * coast_minmes_smart)
if row ['sum_mb'] > mb_included_smart:
summ = summ + (np.ceil((row ['sum_mb'] - mb_included_smart)/1024)*coast_gb_smart)
else:
summ = coast_ultra
if row['sum_duration'] > minutes_included_ultra:
summ = summ + ((row['sum_duration'] - minutes_included_ultra) * coast_minmes_ultra)
if row['count_messages'] > messages_include_ultra:
summ = summ + ((row['count_messages']-messages_include_ultra) * coast_minmes_ultra)
if row ['sum_mb'] > mb_included_ultra:
summ = summ + (np.ceil((row ['sum_mb'] - mb_included_ultra)/1024)*coast_gb_ultra)
return summ
revenue['revenue_sum'] = revenue.apply(revenue_calculation, axis = 1)
display(revenue)
| user_id | month | sum_duration | sum_mb | count_messages | tariff | city | revenue_sum | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1000 | 5 | 159.0 | 2253.49 | 22.0 | ultra | Краснодар | 1950.0 |
| 1 | 1000 | 6 | 172.0 | 23233.77 | 60.0 | ultra | Краснодар | 1950.0 |
| 2 | 1000 | 7 | 340.0 | 14003.64 | 75.0 | ultra | Краснодар | 1950.0 |
| 3 | 1000 | 8 | 408.0 | 14055.93 | 81.0 | ultra | Краснодар | 1950.0 |
| 4 | 1000 | 9 | 466.0 | 14568.91 | 57.0 | ultra | Краснодар | 1950.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3209 | 1489 | 8 | NaN | 11050.56 | 17.0 | smart | Санкт-Петербург | 550.0 |
| 3210 | 1489 | 9 | NaN | 17206.30 | 32.0 | smart | Санкт-Петербург | 950.0 |
| 3211 | 1489 | 10 | NaN | 19559.44 | 21.0 | smart | Санкт-Петербург | 1550.0 |
| 3212 | 1489 | 11 | NaN | 17491.56 | 20.0 | smart | Санкт-Петербург | 1150.0 |
| 3213 | 1489 | 12 | NaN | 17322.51 | 35.0 | smart | Санкт-Петербург | 950.0 |
3214 rows × 8 columns
messages_include_smart = 50
messages_include_ultra = 1000
mb_included_smart = 15360
mb_included_ultra = 30720
minutes_included_smart = data_tariffs[data_tariffs['tariff_name']=='smart']['minutes_included'].values[0]
minutes_included_ultra = 3000
coast_smart = 550
coast_ultra = 1950
coast_gb_smart = 200
coast_gb_ultra = 150
coast_minmes_smart = 3
coast_minmes_ultra = 1
summ=0
def revenue_calculation (row):
name_tariff = row['tariff']
if name_tariff == 'smart':
summ = coast_smart
if row['sum_duration'] > minutes_included_smart:
summ = summ + ((row['sum_duration'] - minutes_included_smart) * coast_minmes_smart)
if row['count_messages'] > messages_include_smart:
summ = summ + ((row['count_messages']-messages_include_smart) * coast_minmes_smart)
if row ['sum_mb'] > mb_included_smart:
summ = summ + (np.ceil((row ['sum_mb'] - mb_included_smart)/1024)*coast_gb_smart)
else:
summ = coast_ultra
if row['sum_duration'] > minutes_included_ultra:
summ = summ + ((row['sum_duration'] - minutes_included_ultra) * coast_minmes_ultra)
if row['count_messages'] > messages_include_ultra:
summ = summ + ((row['count_messages']-messages_include_ultra) * coast_minmes_ultra)
if row ['sum_mb'] > mb_included_ultra:
summ = summ + (np.ceil((row ['sum_mb'] - mb_included_ultra)/1024)*coast_gb_ultra)
return summ
revenue['revenue_sum'] = revenue.apply(revenue_calculation, axis = 1)
display(revenue)
| user_id | month | sum_duration | sum_mb | count_messages | tariff | city | revenue_sum | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1000 | 5 | 159.0 | 2253.49 | 22.0 | ultra | Краснодар | 1950.0 |
| 1 | 1000 | 6 | 172.0 | 23233.77 | 60.0 | ultra | Краснодар | 1950.0 |
| 2 | 1000 | 7 | 340.0 | 14003.64 | 75.0 | ultra | Краснодар | 1950.0 |
| 3 | 1000 | 8 | 408.0 | 14055.93 | 81.0 | ultra | Краснодар | 1950.0 |
| 4 | 1000 | 9 | 466.0 | 14568.91 | 57.0 | ultra | Краснодар | 1950.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3209 | 1489 | 8 | NaN | 11050.56 | 17.0 | smart | Санкт-Петербург | 550.0 |
| 3210 | 1489 | 9 | NaN | 17206.30 | 32.0 | smart | Санкт-Петербург | 950.0 |
| 3211 | 1489 | 10 | NaN | 19559.44 | 21.0 | smart | Санкт-Петербург | 1550.0 |
| 3212 | 1489 | 11 | NaN | 17491.56 | 20.0 | smart | Санкт-Петербург | 1150.0 |
| 3213 | 1489 | 12 | NaN | 17322.51 | 35.0 | smart | Санкт-Петербург | 950.0 |
3214 rows × 8 columns
revenue['revenue_sum'].min()
550.0
revenue['revenue_sum'].max()
6770.0
Создали одну результирующую таблицу, которая содержит в себе информацию, о тарифах и используемых услуг клиента. Теперь легче искать информацию, а также производить с ней операции. Пропуски в данных, говорят об отсусвии звонков или смс, в этот месяц, можем заменить их 0, для чистоты датафрейма.
revenue = revenue.fillna(0)
revenue_analis = revenue.pivot_table(index = 'tariff',values = ['sum_duration','sum_mb','count_messages','revenue_sum'],
aggfunc=('mean','std','var'))
revenue_analis
| count_messages | revenue_sum | sum_duration | sum_mb | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mean | std | var | mean | std | var | mean | std | var | mean | std | var | |
| tariff | ||||||||||||
| smart | 33.384029 | 28.227876 | 796.812958 | 1289.973531 | 818.404367 | 669785.708006 | 417.934948 | 190.313730 | 36219.315784 | 16208.386990 | 5870.476681 | 3.446250e+07 |
| ultra | 49.363452 | 47.804457 | 2285.266143 | 2070.152284 | 376.187114 | 141516.745079 | 526.623350 | 317.606098 | 100873.633397 | 19468.805208 | 10087.170752 | 1.017510e+08 |
Построили сводную таблицу с информацией о тарифах, мы наблюдаем в таблице среднее арфметическое, стандартное отклонение и дисперсию для каждого парметра.
columns = ['sum_duration','sum_mb','count_messages','revenue_sum']
for col in columns:
fig = px.histogram(revenue, x = col, marginal = 'box', color = 'tariff', title = 'Распределение '+col, template = 'plotly_dark')
fig.show()
Выше были построенны гистограммы распределения таких параметров, как кол-во минут и смс, расходованный интрнет трафик и суммарная прибыль с пользователей. Можно сделать следующие выводы:
Приступим к проверке гипотез, у нас их две :
Для начала разберемся с первой, сформулирем нулевую и альтернативную гипотезу:
Приступим к проверке данных гипотез.
from scipy import stats as st
mean_revenue_smart = 2070.152284
alpha = 0.05
results = st.ttest_1samp(revenue[revenue['tariff']== 'smart']['revenue_sum'],mean_revenue_smart )
print('p-значение: ', results.pvalue)
if results.pvalue < alpha:
print("Отвергаем нулевую гипотезу")
else:
print("Не получилось отвергнуть нулевую гипотезу")
p-значение: 3.36352117e-315 Отвергаем нулевую гипотезу
Средняя выручка пользователей двух тарифов не равна. Далее составим нулевую и альтернативную гипотезы для следующей проверки:
mean_revenue_msk = revenue[revenue['city']=='Москва']['revenue_sum'].mean()
alpha = 0.05
results = st.ttest_1samp(revenue[revenue['city']!= 'Москва']['revenue_sum'],mean_revenue_msk )
print('p-значение: ', results.pvalue)
if results.pvalue < alpha:
print("Отвергаем нулевую гипотезу")
else:
print("Не получилось отвергнуть нулевую гипотезу")
p-значение: 0.1696376636320093 Не получилось отвергнуть нулевую гипотезу
По проверки гипотез, можно сделать вывод, что средняя выручка пользователей двух тарифов отличается, а вот выручка пользователей Москвы и других регионов не отличается.
В ходе проекта проанализировали информацию о пользователях двух тарифов. Исправили ошибки в данных и недочеты. Можем говорить о выводах полученных в результате анализа:
Для получения данных выводов, нам было необходи сгруппировать данные, объеденить необходимые парамметры для анализа, в одну таблицу, чтобы удобнее было представлять данные и обращаться к ним, перед группировкой была необходимость познакомиться с данными, привести все необходимые колонки к верному типу данных, и округлить значения, для расчетов прибыли, в соотвесвиями с условиями тарифных планов.